home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / snd_amiga.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  8KB  |  262 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // snd_amiga.c
  21.  
  22. #include <exec/exec.h>
  23. #include <dos/dos.h>
  24. #include <graphics/gfxbase.h>
  25. #include <devices/audio.h>
  26.  
  27. #include <powerpc/powerpc.h>
  28. #include <powerpc/powerpc_protos.h>
  29. extern struct GfxBase *GfxBase;
  30.  
  31. #include <powerup/ppcproto/exec.h>
  32. #include <powerup/ppcproto/dos.h>
  33. #include <powerup/ppcproto/graphics.h>
  34.  
  35. #include "quakedef.h"
  36.  
  37. #define    BeginIO(ioRequest) _BeginIO(ioRequest)
  38. __inline void
  39. _BeginIO(struct IORequest *ioRequest)
  40. {
  41. struct PPCArgs    args;
  42.     memset(&args,0,sizeof(args));
  43.     args.PP_Code        =(APTR) ioRequest->io_Device;
  44.     args.PP_Offset        =    (-30);
  45.     args.PP_Flags        =    0;
  46.     args.PP_Regs[PPREG_A1]    =(ULONG) ioRequest;
  47.     args.PP_Regs[PPREG_A6]    =(ULONG) ioRequest->io_Device;
  48.     Run68K (&args);
  49. }
  50.  
  51. /**********************************************************************/
  52.  
  53. extern int desired_speed;
  54. extern int desired_bits;
  55.  
  56. /**********************************************************************/
  57.  
  58. #define MAXNUMCHANNELS   4   /* max number of Amiga sound channels */
  59. /* #define BUFFERSIZE 16384 */
  60. #define BUFFERSIZE 4096
  61.  
  62. struct channel_info {
  63.   struct MsgPort *audio_mp;
  64.   struct IOAudio *audio_io;
  65.   double starttime;
  66.   BOOL sound_in_progress;
  67. };
  68.  
  69. static struct channel_info channel_info[MAXNUMCHANNELS] = {
  70.   {NULL, NULL, FALSE},
  71.   {NULL, NULL, FALSE},
  72.   {NULL, NULL, FALSE},
  73.   {NULL, NULL, FALSE},
  74. };
  75.  
  76. static int size;
  77.  
  78. static struct MsgPort *audio_mp = NULL;
  79. static struct IOAudio *audio_io = NULL;
  80. static BOOL audio_is_open = FALSE;
  81. static ULONG clock_constant;   /* see Amiga Hardware Manual page 141 */
  82. static UWORD period;
  83. static double twice_real_speed;
  84.  
  85. /**********************************************************************/
  86. // Stops a sound channel.
  87.  
  88. static void stopsound (int cnum)
  89. {
  90.   if (!audio_is_open)
  91.     return;
  92.   if (channel_info[cnum].sound_in_progress) {
  93.     AbortIO ((struct IORequest *)channel_info[cnum].audio_io);
  94.     WaitPort (channel_info[cnum].audio_mp);
  95.     GetMsg (channel_info[cnum].audio_mp);
  96.     channel_info[cnum].sound_in_progress = FALSE;
  97.   }
  98. }
  99.  
  100. /**********************************************************************/
  101. // Starts a sound in a particular sound channel.
  102.  
  103. static int startsound (int cnum, char *buffer, int length)
  104. {
  105.   struct channel_info *c;
  106.  
  107.   if (!audio_is_open)
  108.     return 1;
  109.   stopsound (cnum);
  110.   c = &channel_info[cnum];
  111.   c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  112.   c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  113.   c->audio_io->ioa_Data = buffer;
  114.   c->audio_io->ioa_Length = length;
  115.   c->audio_io->ioa_Period = period;
  116.   c->audio_io->ioa_Volume = 64;
  117.   c->audio_io->ioa_Cycles = 0;
  118.   BeginIO ((struct IORequest *)c->audio_io);
  119.   c->starttime = Sys_FloatTime ();
  120.   c->sound_in_progress = TRUE;
  121.   return cnum;
  122. }
  123.  
  124. /**********************************************************************/
  125.  
  126. qboolean SNDDMA_Init (void)
  127. {
  128.   int i;
  129.   struct channel_info *c;
  130.   UBYTE chans[1];
  131.  
  132. //  printf ("SNDDMA_Init()\n");
  133.  
  134.   if ((shm = (dma_t *)malloc (sizeof(dma_t))) == NULL)
  135.     Sys_Error ("malloc() failed");
  136.   memset((void*)shm, 0, sizeof(dma_t));
  137.  
  138.   if ((shm->buffer = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_CLEAR)) == NULL)
  139.     Sys_Error ("Out of CHIP memory for sound");
  140. //  memset(shm->buffer, 0x80, BUFFERSIZE);
  141.  
  142. //  printf ("Sound buffer at 0x%08x\n", shm->buffer);
  143.  
  144.   shm->channels = 2;
  145.   shm->speed = desired_speed;
  146.   shm->samplebits = 8;
  147.   shm->samples = BUFFERSIZE / (shm->samplebits / 8);
  148.   shm->submission_chunk = 1;
  149.  
  150.   if ((audio_mp = CreateMsgPort ()) == NULL ||
  151.       (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  152.                                            MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  153.     Sys_Error ("CreateMsgPort() or AllocMem() failed");
  154.  
  155.   chans[0] = (1 << shm->channels) - 1; /* shm->channels Amiga audio channels */
  156.   audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  157.   audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  158.   audio_io->ioa_AllocKey = 0;
  159.   audio_io->ioa_Data = chans;
  160.   audio_io->ioa_Length = sizeof(chans);
  161.  
  162.   if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
  163.     Sys_Error ("OpenDevice(\"audio.device\") failed");
  164.   audio_is_open = TRUE;
  165.  
  166.   for (i = 0; i < shm->channels; i++) {
  167.     c = &channel_info[i];
  168.     if ((c->audio_mp = CreateMsgPort ()) == NULL ||
  169.         (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  170.                                            MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  171.       Sys_Error ("CreateMsgPort() or AllocMem() failed");
  172.     *c->audio_io = *audio_io;
  173.     c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  174.     c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  175.   }
  176.  
  177.   if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
  178.     clock_constant = 3579545;   /* NTSC */
  179.   else
  180.     clock_constant = 3546895;   /* PAL */
  181.  
  182.   period = ((clock_constant << 1) + shm->speed) / ((shm->speed) << 1);
  183.  
  184.   twice_real_speed = 2.0 * ((double)clock_constant) / (double)period;
  185.  
  186.   startsound (0, shm->buffer, BUFFERSIZE >> 1);
  187.   startsound (1, shm->buffer + (BUFFERSIZE >> 1), BUFFERSIZE >> 1);
  188.  
  189.   return 1;
  190. }
  191.  
  192. /**********************************************************************/
  193.  
  194. int SNDDMA_GetDMAPos (void)
  195. {
  196.   if (shm == NULL || shm->buffer == NULL || !channel_info[0].sound_in_progress)
  197.     return 0;
  198.  
  199.   shm->samplepos = ((int)((Sys_FloatTime() - channel_info[0].starttime)
  200.                           * twice_real_speed + 0.5))
  201.                    & (BUFFERSIZE - 1);
  202.  
  203. //  shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1);
  204.  
  205. //  if (pos < 0 || pos >= BUFFERSIZE)
  206. //    Sys_Error ("pos = %d is out of range\n");
  207.   return shm->samplepos;
  208. }
  209.  
  210. /**********************************************************************/
  211.  
  212. void SNDDMA_Shutdown (void)
  213. {
  214.   int i;
  215.  
  216. //  printf ("SNDDMA_Shutdown()\n");
  217.  
  218.   if (audio_is_open) {
  219.     if (shm != NULL) {
  220.       for (i = 0; i < shm->channels; i++)
  221.         stopsound (i);
  222.       audio_io->ioa_Request.io_Unit = (struct Unit *)
  223.                        ((1 << shm->channels) - 1);  /* free shm->channels channels */
  224.     }
  225.     CloseDevice ((struct IORequest *)audio_io);
  226.     audio_is_open = FALSE;
  227.   }
  228.   for (i = 0; i < MAXNUMCHANNELS; i++) {
  229.     if (channel_info[i].audio_io != NULL) {
  230.       FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  231.       channel_info[i].audio_io = NULL;
  232.     }
  233.     if (channel_info[i].audio_mp != NULL) {
  234.       DeleteMsgPort (channel_info[i].audio_mp);
  235.       channel_info[i].audio_mp = NULL;
  236.     }
  237.   }
  238.   if (audio_io != NULL) {
  239.     FreeMem (audio_io, sizeof(struct IOAudio));
  240.     audio_io = NULL;
  241.   }
  242.   if (audio_mp != NULL) {
  243.     DeleteMsgPort (audio_mp);
  244.     audio_mp = NULL;
  245.   }
  246.   if (shm != NULL) {
  247.     if (shm->buffer != NULL) {
  248.       FreeMem (shm->buffer, BUFFERSIZE);
  249.       shm->buffer = NULL;
  250.     }
  251.     free ((char *)shm);
  252.     shm = NULL;
  253.   }
  254. }
  255.  
  256. void SNDDMA_Submit (void)
  257. {
  258. //  printf ("SNDDMA_Submit()\n");
  259. }
  260.  
  261. /**********************************************************************/
  262.